package cruncher;

import java.util.Collection;
import java.util.Collections;
import java.util.PriorityQueue;
import java.util.Comparator;
import java.util.Random;

/***
 * Solution pool with limited size
 * Returns random solution, removes maximal
 * @author igorzar
 *
 */
public class LimitedSolutionPool implements ISolutionPool {
	private PriorityQueue<Solution> pool = null;
	protected int poolSizeLimit;
	
	public LimitedSolutionPool(int poolSize)
	{
		this.poolSizeLimit = poolSize;
		
		pool = new PriorityQueue<Solution>(poolSize,
			new Comparator<Solution>()
				{	//max comes before min
					public int compare(Solution a, Solution b)
					{
						return -1 * Double.compare(a.getObjValue(), b.getObjValue());
					}
				});
	}
	


	@Override
	public void addSolution(Solution s) {
		//if (!this.isBetterSolution(s)) return;
		
		if (pool.size() < poolSizeLimit)
		{
			pool.offer(s);
			return;
		}
		
		//need to remove maximal value
		pool.poll();
		pool.offer(s);
		
	}

	@Override
	public Solution getRandom() {
		if (size()==0) return null;
		if (size()==1) return pool.peek();
		
		Random rnd = new Random(System.currentTimeMillis());
		Solution[] solutions = pool.toArray(new Solution[0]);
		return solutions[rnd.nextInt(solutions.length - 1)];
	}

	@Override
	public boolean isBetterSolution(Solution next) {
		//Compare to max solution
		if (next == null) return false;
		if (getMax() == null) return true;
		return next.getObjValue() < getMax().getObjValue(); 
	}

	@Override
	public Solution getMin() {
		//Return in reverse order, smaller first
		return Collections.min(pool, Collections.reverseOrder(pool.comparator()));
	}

	@Override
	public Solution getMax() {
		return pool.peek();
	}
	
	@Override
	public int size() {
		return pool.size();
	}


	@Override
	public void replaceSolution(Solution oldS, Solution newS) {
		pool.remove(oldS);
		pool.add(newS);
	}

}
